#include "qq.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#define QQ_URL_MAX 60
HttpQQ::HttpQQ(const char *datadir)
{
    this->datadir=strdup(datadir);

    this->request=gfw_init();
    gfw_add_unique_header(this->request,"User-Agent","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12");
    gfw_add_unique_header(this->request,"Accept-Language","zh-cn,zh;q=0.5");
    gfw_add_unique_header(this->request,"Accept-Charset","gb2312,utf-8;q=0.7,*;q=0.7");
    gfw_add_unique_header(this->request,"Referer","http://group.qq.com/");
}
HttpQQ::~HttpQQ()
{
    free(this->datadir);
    if (this->cookie_path) {
        free(this->cookie_path);
    }
    if (this->verify_image) {
        free(this->verify_image);
    }
    gfw_free(this->request);
}

bool HttpQQ::InitWithCookie(uint32_t qq)
{
    this->cookie_path=(char *)malloc(9+strlen(this->datadir)+10);
    sprintf(this->cookie_path,"%s/%d/cookie",this->datadir,qq);
    if (gfw_load_cookie_holder(this->request,this->cookie_path)==false) {
        return false;
    }
    this->LoadGroup();
    if (this->groups.size()<=0) {
        return false;
    }
    return true;
}

bool HttpQQ::InitLogin()
{
    char url[QQ_URL_MAX];
    time_t t;
    time(&t);
    sprintf(url,"http://ptlogin2.qq.com/getimage?aid=3000801&0.%d",t);
    gfw_set_url(this->request,url);
    gfw_set_method(this->request,"GET");
    gfw_add_unique_header(this->request,"Accept","image/png,*/*;q=0.5");
    gfw_response *gres=gfw_send(this->request);
    if (!strcmp(gres->status,"200") && gres->body) {
        this->verify_image=gres->body;
        gfw_response_free(gres);
        return true;
    } else {
        gfw_response_free(gres);
        return false;
    }
}
bool HttpQQ::Login(uint32_t qq,char *password,char *verify_code)
{
    gfw_set_url(this->request,"http://ptlogin2.qq.com/login");
    gfw_set_method(this->request,"POST");
    gfw_add_unique_header(this->request,"Accept","text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
    gfw_clear_post_data(this->request);
    gfw_add_post_data(this->request,"dummy","1");
    gfw_add_post_data(this->request,"aid","3000801");
    gfw_add_post_data(this->request,"fp","loginerroralert");
    gfw_add_post_data(this->request,"u1","http://group.qq.com/login/login_success.htm");
    char qq_str[11];
    sprintf(qq_str,"%d",qq);
    gfw_add_post_data(this->request,"u",qq_str);
    gfw_add_post_data(this->request,"p",password);
    gfw_add_post_data(this->request,"verifycode",verify_code);
    gfw_response *gres=gfw_send(this->request);
    gfw_response_free(gres);
    this->LoadGroup();
    if (this->groups.size()<=0) {
        return false;
    }
    return true;
}

bool HttpQQ::LoadGroup() 
{
    int p=1;
    gfw_set_method(this->request,"GET");
    gfw_response *gres;
    uint32_t group_id;
    char *name;
    char *gonggao;
    vector<group_info> groups_info;
    group_info gi;
    int i=0;
    char url[QQ_URL_MAX];
    while (1) {
        sprintf(url,"http://group.qq.com/cgi-bin/grouplist?p=%d",p);
        gfw_set_url(this->request,url);
        ++p;
        gres=gfw_send(this->request);
        if (!gres) {
            break;
        }

        groups_info=this->ParseGroupList(gres->body);
        gfw_response_free(gres);

        if (groups_info.size()<=0) {
            break;
        }
        for (i=0;i<groups_info.size();i++) {
            gi=groups_info.at(i);
            this->groups.push_back(new QQGroup(this,gi.id,gi.name));
            free(gi.id);
            free(gi.name);
        }
    }
    return true;
}

vector<group_info> HttpQQ::ParseGroupList(const char *html)
{
    vector<group_info> gis;
    group_info gi;
    regex_t preg;
    int     status;
    regmatch_t pmatch[3];

    char *id;
    char *name;
    int id_len,name_len;

    regcomp(&preg,"groupid=([0-9]+)[^>]+>([^<]+)</a></strong>",REG_EXTENDED);
    while (status = regexec( &preg, html, 3, pmatch, 0)== 0) {
        id_len=pmatch[1].rm_eo-pmatch[1].rm_so;
        name_len=pmatch[2].rm_eo-pmatch[2].rm_so;
        id=(char *)malloc(id_len+1);
        name=(char *)malloc(name_len+1);
        id[id_len]=0;
        name[name_len]=0;
        memcpy(id,html+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so);
        memcpy(name,html+pmatch[2].rm_so,pmatch[2].rm_eo-pmatch[2].rm_so);
        html+=pmatch[0].rm_eo;
        gi.id=id;
        gi.name=name;
        gis.push_back(gi);
    }
    return gis;
}


QQGroup::QQGroup(HttpQQ *http_qq,char *group_id,const char *name)
{
    this->qq=http_qq;

    this->id=strdup(group_id);
    this->name=strdup(name);
    this->gonggao=NULL;
}
bool QQGroup::LoadGonggao()
{
    char url[QQ_URL_MAX];
    sprintf(url,"http://group.qq.com/cgi-bin/show_memopage?groupid=%s",this->id);
    gfw_set_url(this->qq->request,url);
    gfw_set_method(this->qq->request,"GET");
    gfw_response *gres=gfw_send(this->qq->request);
    char *html=gres->body;
    regex_t preg;
    int     status;
    regmatch_t pmatch[2];

    char *gonggao;
    int len;

    regcomp(&preg,"<textarea[^>]+>([^<]+)   </textarea>",REG_EXTENDED);
    if (status = regexec( &preg, html, 2, pmatch, 0)== 0) {
        len=pmatch[1].rm_eo-pmatch[1].rm_so;
        gonggao=(char *)malloc(len+1);
        gonggao[len]=0;
        memcpy(gonggao,html+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so);
        gfw_url_decode(gonggao);
        gfw_response_free(gres);
        this->gonggao=gonggao;
        return true;
    } else {
        gfw_response_free(gres);
        return false;
    }
}
bool QQGroup::ChangeGonggao(char *gonggao)
{
    gfw_set_url(this->qq->request,"http://group.qq.com/cgi-bin/changememo");
    gfw_set_method(this->qq->request,"POST");
    gfw_clear_post_data(this->qq->request);
    gfw_add_post_data(this->qq->request,"groupid",this->id);
    gfw_add_post_data(this->qq->request,"type","0");
    gfw_add_post_data(this->qq->request,"memo",gonggao);
    gfw_add_post_data(this->qq->request,"image.x","67");
    gfw_add_post_data(this->qq->request,"image.y","9");
    gfw_response *gres=gfw_send(this->qq->request);
    gfw_response_free(gres);
    return true;
}
